/*
 * EntityLauncher.java
 *
 * $Id: EntityLauncher.java,v 1.23 2009-10-07 10:19:39 juancarlos Exp $
 */
package org.ceteca.explica.core.installer;

import java.rmi.AccessException;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;

import org.ceteca.explica.client.ClientContext;
import org.ceteca.explica.client.gui.EntityExtensionCatalogListener;
import org.ceteca.explica.client.gui.ExplicaDetailEntityView;
import org.ceteca.explica.client.gui.ExplicaEditEntityView;
import org.ceteca.explica.client.gui.ExplicaEntitySelectionView;
import org.ceteca.explica.client.gui.ExplicaEntityView;
import org.ceteca.explica.client.gui.ExplicaGUIBuilder;
import org.ceteca.explica.core.ExplicaException;
import org.ceteca.explica.core.InterfaceErrors;
import org.ceteca.explica.core.InterfaceExplica;
import org.ceteca.explica.core.common.BaseVO;
import org.ceteca.explica.core.common.CommonManager;
import org.ceteca.explica.core.common.MultiSelectionSubentityOT;
import org.ceteca.explica.core.common.RegistryOT;
import org.ceteca.explica.core.extTables.ExtFieldOT;
import org.ceteca.explica.core.extTables.ExtTableException;
import org.ceteca.explica.core.extTables.ExtTableOT;
import org.ceteca.explica.core.util.OperationResult;
import org.ceteca.explica.core.util.ResultMessage;
import org.ceteca.javaglade.Gui;
import org.ceteca.javaglade.InterfaceGladeGtk;
import org.ceteca.javaglade.JavaGlade;
import org.ceteca.javaglade.toolkit.swt.SwtDialog;
import org.ceteca.javaglade.toolkit.swt.SwtWidget;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StackLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeColumn;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.swt.widgets.Widget;
import org.apache.log4j.Logger;

/**
 * Generic class that defines the common operations of the main class of each
 * entity. <br/> Responsibilities:
 * <ul>
 * <li>Provide a method for initializing and configuring an entity.</li>
 * <li>Provide a method for building the GUI of an entity.</li>
 * <li>Provide a method for handling the add entity event.</li>
 * <li>Provide a method for handling the delete entity event.</li>
 * <li>Provide a method for handling the edit entity event.</li>
 * <li>Provide a method for handling the print entity event.</li>
 * <li>Provide a method for handling the search entity event.</li>
 * <li>Provide a method for handling the select entity event.</li>
 * <li>Keep an instance of the logger for the entity.</li>
 * </ul>
 * <br/>
 * 
 * @author Mario García García <mario@imagos.es> Copyright (c) 2007 Fundación
 *         Centro Tecnolóxico da Carne This program is free software: you can
 *         redistribute it and/or modify it under the terms of the GNU General
 *         Public License as published by the Free Software Foundation, either
 *         version 3 of the License, or (at your option) any later version.
 *         <br/> This program is distributed in the hope that it will be useful,
 *         but WITHOUT ANY WARRANTY; without even the implied warranty of
 *         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 *         General Public License for more details. <br/> You should have
 *         received a copy of the GNU General Public License along with this
 *         program. If not, see <http://www.gnu.org/licenses/>.
 */
public abstract class EntityLauncher {
	/**
	 * Constant value with the logging message for an error ocurred during the
	 * initialization of the entity (the flag entityReady is unset).
	 */
	public static final String ERROR_START_ENTITY = "Cannot start the entity. The entity was not correctly initialized and cannot be started!";

	/**
	 * Constant value with the logging message for an error ocurred during the
	 * building of the entity panel.
	 */
	public static final String ERROR_BUILD_ENTITY_PANEL = "Cannot start the entity. The entity view couldn't be built!";

	/**
	 * Constant value with the logging message for starting a new entity.
	 */
	public static final String ENTITY_START = "Starting entity: %s";

	/**
	 * Constant value with the logging message for an error ocurred during the
	 * instantiation of the entity's helper class.
	 */
	public static final String ERROR_ENTITY_NOHELPERINSTANCE = "An instance of the entity's helper class couldn't be created!";

	/**
	 * List of searched registries for the entity.
	 */
	protected ArrayList<BaseVO> lRegistries;
	
	/**
	 * Value object instance with the data of the selected entity's registry.
	 */
	protected BaseVO selectedEntity = null;
	
	/**
	 * Parent panel where the entity view will be embedded.
	 */
	protected SwtWidget parentPanel;

	/** Parent GUI where the entity panel will be embedded */
	protected Gui parentGui;

	/** Name of the entity GUI */
	protected String entityGuiName;

	/** Name of the entity edition GUI */
	protected String entityEditGuiName;
	
	/** Name of the entity selection GUI */
	protected String entitySelectionGuiName;

	/** Data of the entity the launcher is built for. */
	protected EntityOT entityData;
	
	protected Composite entityPanel;

	/**
	 * Instance of the ExplicaDetailEntityView that will construct the view for
	 * the entity.
	 */
	protected ExplicaDetailEntityView entityDetailView;

	/**
	 * Instance of the ExplicaEntityView component that will show the entity data.
	 */
	protected ExplicaEntityView entView;

	/**
	 * Instance of the subentity selection view used in the entity edition
	 * window.
	 */
	protected ExplicaEntitySelectionView entSelView;
	
	/**
	 * Instance of the edition view used in the entity edition
	 * window.
	 */
	protected ExplicaEditEntityView entEditView;

	/**
	 * Instance of the logging system for the entity.
	 */
	protected Logger logger;

	/**
	 * Flag to show when the entity is ready to be started, that is, the entity
	 * has been correctly initialized and configured. If any error takes places
	 * during initialization phase, this flag will be unset.
	 */
	protected boolean entityReady;

	/**
	 * Instance of the Dialog window built for showing the entity data. It will
	 * be null until it's built for the first time (as the result of an edit or
	 * new entity operation). After that the same instance of the dialog will be
	 * used for the rest of operations.
	 */
	protected SwtDialog entityDialog;

	protected EntityLauncher() {
		this.logger = null;
		this.entView = null;
		this.entEditView = null;
		this.entityDetailView = null;
		this.entityData = null;
		this.lRegistries = null;
		this.parentGui = null;
		this.entityGuiName = null;
		this.entitySelectionGuiName = null;
		this.entityEditGuiName = null;
		this.entityReady = false;
		this.parentPanel = null;
	}
	
	/**
	 * Getter for lRegistries
	 */
	public ArrayList<BaseVO> getLRegistries() {
		return lRegistries;
	}

	/**
	 * Add entity button clicked handler. Show the entity content screen ready
	 * to start inserting data for a new instance of the entity (new registry).
	 * 
	 * @return ArrayList<ResultMessage>, list of errors if any has taken place,
	 *         null in any other case.
	 */
	public abstract ArrayList<ResultMessage> addEntity();

	/**
	 * Delete entity button clicked handler. Deletes the selected instance of
	 * the entity (selected registry) from the database.
	 * 
	 * @return OperationResult, result of the delete operation and list of
	 *         messages generated during the operation.
	 */
	public abstract OperationResult delEntity();

	/**
	 * Delete entity button clicked handler. Deletes the selected instances of
	 * the entity (selected registries) from the database. Its a multiple delete
	 * method.
	 * 
	 * @param lSelRegistries
	 *            ArrayList<Long>, list of selected instances of the entity
	 *            (selected registries). The list will contain only the internal
	 *            id of the selected registries.
	 * @return OperationResult, result of the delete operation and list of
	 *         messages generated during the operation.
	 */
	public abstract OperationResult delEntity(ArrayList<Long> lSelRegistries);

	/**
	 * Edit entity button clicked handler. Show the entity content screen filled
	 * with the data of the selected instance of the entity (selected registry),
	 * and allows the user to modify any content of the entity registry.
	 * 
	 * @return OperationResult, result of the delete operation and list of
	 *         messages generated during the operation.
	 */
	public abstract OperationResult editEntity();

	/**
	 * View entity button clicked handler. Show the entity content screen filled
	 * with the data of the selected instance of the entity (selected registry),
	 * in read-only mode.
	 * 
	 * @return OperationResult, result of the delete operation and list of
	 *         messages generated during the operation.
	 */
	public abstract OperationResult viewEntity();

	/**
	 * Print entity button clicked handler. Builds the report with the data of
	 * the selected instance of the entity (selected registry), and allows the
	 * user to print the elaborated report.
	 * 
	 * @return OperationResult, result of the delete operation and list of
	 *         messages generated during the operation.
	 */
	public abstract OperationResult printEntity();

	/**
	 * Search entity button clicked handler. Searches the system for the entity
	 * instances (registries) available.
	 * 
	 * @return ArrayList, list of entity instances (registries) taken as the
	 *         result of the query operation.
	 */
	public abstract ArrayList queryEntity();

	/**
	 * Search entity button clicked handler. Searches the system for the entity
	 * instances (registries) that fit a searching criteria.
	 * 
	 * @param fieldId
	 *            String, name of the entity field that will be queried.
	 * @param value
	 *            String, value of the entity field that will be searched for.
	 * @return ArrayList, list of entity instances (registries) taken as the
	 *         result of the query operation.
	 */
	public abstract ArrayList queryEntity(String fieldId, String value);

	/**
	 * Search entity button clicked handler. Searches the system for the entity
	 * instances (registries) that fit a searching criteria and show them
	 * (formatted as a list) to the user in the entity's screen.
	 * 
	 * @param fieldId
	 *            String, name of the entity field that will be queried.
	 * @param value
	 *            String, value of the entity field that will be searched for.
	 * @return ArrayList<RegistryOT>, list of entity instances (registries)
	 *         taken as the result of the query operation.
	 */
	public abstract ArrayList<RegistryOT> queryEntityWithFormat(String fieldId,
			String value);

	/**
	 * Save entity button clicked handler. Update the system with the data of
	 * the edited entity registry. It's called for saving new entity registries
	 * (add a new registry) or for updating the contents of existing entity
	 * registries.
	 * 
	 * @return OperationResult, Result of the operation and list of messages
	 *         generated through the operation.
	 */
	public abstract OperationResult saveEntity();

	/**
	 * Fills the entity content panel with the data of the selected instance
	 * (registry) of the entity.
	 */
	public abstract void fillEntityData();

	/**
	 * Clears the entity content panel by reseting the content widgets.
	 */
	public abstract void clearEntityData();

	/**
	 * Updates the selected instance (registry) data with the content panel's
	 * data typed by the user.
	 */
	public abstract void updateEntityData();

	/**
	 * Gets the content panel's data typed by the user formatted as an entity VO
	 * object.
	 */
	public abstract BaseVO getEntityData();

	/**
	 * Marks an instance (registry) of the entity as the selected.
	 * 
	 * @param idEntity
	 *            Long, internal id of the selected instance (registry).
	 */
	public abstract void selectEntity(Long idEntity);

	/**
	 * Gets the selected instance (registry) of the entity.
	 * 
	 * @return BaseVO, selected instance (registry) of the entity.
	 */
	public BaseVO getSelectedEntity() {
		return this.selectedEntity;
	}

	/**
	 * Connects the subentity selection buttons with their handlers.
	 */
	protected abstract void connectSubentityButtons();

	/**
	 * Updates an entity instance by setting up the selected value for a
	 * subentity field.
	 * 
	 * @param parentFieldId
	 *            String, name of the parent entity field updated. It's the
	 *            parent entity field whose subentity value has been setted up.
	 * @param subentityOT
	 *            BaseVO, subentity's selected instance (registry) value.
	 */
	public void selectSubentity(String parentFieldId, BaseVO subentityOT) {
		if (parentFieldId != null && parentFieldId.length() > 0
				&& subentityOT != null) {
			this.logger.debug(String.format(
					"Setting up a new value for the field %s: %s",
					parentFieldId, subentityOT));
			try {
				ExplicaGUIBuilder.getInstance().printGUIs(this.logger);
				Widget widget = this.getWidget(parentFieldId);
				widget.setData(subentityOT);
				if (widget instanceof Text) {
					Text entry = (Text) widget;
					entry.setText(subentityOT.getInternalValue());
				} else if (widget instanceof Tree) {
					EntityOT entOT = ClientContext.getInstance().getEntity(
							subentityOT.getEntityId());

					this.logger.debug("\\\\ LISTA DE CAMPOS: ////");
					for (FieldOT f : entOT.getLFields()) {
						this.logger.debug("\t\\\\ " + f.getId());
					}
					this.logger.debug("\\\\ FIN LISTA DE CAMPOS: ////");
					Tree tree = (Tree) widget;
					boolean itemExists = false;
					for (int i = 0; i < tree.getItemCount() && !itemExists; i++) {
						TreeItem it = tree.getItem(i);
						itemExists = it.getText(0).equalsIgnoreCase(
								String
										.format("%d", subentityOT
												.getInternalId()));
						this.logger.debug(String.format(
								".-.-.- Subentity exists? %s == %d, %b", it
										.getText(0), subentityOT
										.getInternalId(), itemExists));
					}

					// Add registry to the entity table
					if (!itemExists) {
						TreeItem treeItem = (TreeItem) ExplicaGUIBuilder
								.getInstance()
								.getToolkit()
								.treeItem(
										tree,
										InterfaceExplica.EXPLICA_ENTITY_TREEITEM_NAME
												+ "_"
												+ subentityOT.getInternalId(),
										subentityOT.format(entOT.getIdField(),
												entOT.getLFields()), null, -1);
					} else {
						this.logger.debug("Subentity already selected");
					}
					tree.layout(false);
				}
			} catch (Exception ex) {
				ex.printStackTrace();
				this.logger
						.error(
								String
										.format(
												"Error updating the selected subentity field %s with the value %s",
												parentFieldId, subentityOT), ex);
			}
		} else {
			this.logger
					.error(String
							.format(
									"Error setting up a new value for a subentity (%s) field! The field name is null or empty!",
									subentityOT == null ? "NULL" : subentityOT
											.getClass().toString()));
		}
	}
	
	/**
	 * Updates an entity instance by removing the selected value for a
	 * subentity field.
	 * 
	 * @param parentFieldId
	 *            String, name of the parent entity field updated. It's the
	 *            parent entity field whose subentity value has been setted up.
	 * @param subentityOT
	 *            BaseVO, subentity's deselected instance (registry) value.
	 */
	public void deselectSubentity(String parentFieldId, BaseVO subentityOT) {
		if (parentFieldId != null && parentFieldId.length() > 0
				&& subentityOT != null) {
			this.logger.debug(String.format(
					"Removing a value for the field %s: %s",
					parentFieldId, subentityOT));
			try {
				ExplicaGUIBuilder.getInstance().printGUIs(this.logger);
				Widget widget = this.getWidget(parentFieldId);
				if (widget instanceof Text) {
					Text entry = (Text) widget;
					entry.setText("");
				} else if (widget instanceof Tree) {
					EntityOT entOT = ClientContext.getInstance().getEntity(
							subentityOT.getEntityId());

					this.logger.debug("\\\\ LISTA DE CAMPOS: ////");
					for (FieldOT f : entOT.getLFields()) {
						this.logger.debug("\t\\\\ " + f.getId());
					}
					this.logger.debug("\\\\ FIN LISTA DE CAMPOS: ////");
					Tree tree = (Tree) widget;
					boolean itemExists = false;
					// Remove the deselected registry from the entity table (if it exists)
					for (int i = 0; i < tree.getItemCount() && !itemExists; i++) {
						TreeItem it = tree.getItem(i);
						itemExists = it.getText(0).equalsIgnoreCase(
								String
										.format("%d", subentityOT
												.getInternalId()));
						this.logger.debug(String.format(
								".-.-.- Subentity exists? %s == %d, %b", it
										.getText(0), subentityOT
										.getInternalId(), itemExists));
						
						if (itemExists)
							it.dispose();
					}
				}
			} catch (Exception ex) {
				ex.printStackTrace();
				this.logger
						.error(
								String
										.format(
												"Error updating the deselected subentity field %s with the value %s",
												parentFieldId, subentityOT), ex);
			}
		} else {
			this.logger
					.error(String
							.format(
									"Error removing a value for a subentity (%s) field! The field name is null or empty!",
									subentityOT == null ? "NULL" : subentityOT
											.getClass().toString()));
		}
	}

	/**
	 * Gets the list of defined fields for an entity
	 * 
	 * @return ArrayList, list of entity fields.
	 */
	public abstract ArrayList getEntityFields();

	/**
	 * Gets the internal id of the selected entity registry.
	 * 
	 * @return Long, internal id of the selected entity registry, null in case
	 *         no entity registry has been selected yet.
	 */
	public Long getSelectedId() {
		return (this.selectedEntity == null ? null : this.selectedEntity
				.getInternalId());
	}

	/**
	 * Queries the selected entity for all the detail subentities associated
	 * with it.
	 * 
	 * @param entData
	 *            SubentityOT, data of the detail subentity to query for.
	 * @return ArrayList, list of detail subentity registries assigned to the
	 *         master detail registry.
	 */
	public abstract ArrayList querySubentities(SubentityOT entData);

	/**
	 * Opens the selection dialog that enables the user to select an instance of
	 * a multiple selection detail subentity.
	 * 
	 * @param entData
	 *            SubentityOT, data of the detail subentity to select.
	 */
	public void showSubentitySelectionDialog(SubentityOT entData) {
		this.logger.info("ÇÇÇÇ SHOWING SUBENTITY SELECTION DIALOG: "
				+ entData.getSubentityData().getKey() + ", " + this.entSelView
				+ " ÇÇÇÇ");
		if (this.entSelView != null)
			this.entSelView.showSubentitySelection(entData);
		else
			this.logger
					.error("Entity selection dialog hasn't been configured for this entity: "
							+ this.entityGuiName);
	}

	/**
	 * Opens the edition dialog that enables the user to update or view the
	 * instance data of a multiple selection detail subentity.
	 * 
	 * @param entData
	 *            SubentityOT, data of the detail subentity to select.
	 * @param selEntity
	 *            long, id of the selected instance of the subentity.
	 * @param readonly
	 *            boolean, true for enabling the read-only mode (only view);
	 *            false for allowing modification of the showed data.
	 */
	public void showSubentityDialog(SubentityOT entData, long selEntity,
			boolean readonly) {
/*		this.logger.info("ÇÇÇÇ SHOWING SUBENTITY DIALOG: "
				+ entData.getSubentityData().getKey() + ", " + this.entSelView
				+ " ÇÇÇÇ");
		// Get the entity launcher factory for creating a new entity launcher
		// that will handle the entity events.
		EntityLauncherFactory factory = ClientContext.getInstance()
				.getEntityLauncherFactory(entData.getSubentityData().getKey());

		// Get the entity launcher instance that will handle the entity events
		EntityLauncher entLauncher = factory
				.getEntityLauncher(this.entityEditGuiName);

		this.logger.info("GOT ENTITY LAUNCHER: " + entLauncher);

		if (entLauncher != null) {
			entLauncher.initEntityLauncher(this.logger, this.entityEditGuiName, null);
		} else
			this.logger.error(ERROR_ENTITY_NOHELPERINSTANCE);

		// Build the subentity edition dialog
		entLauncher.buildEditEntityGUI();

		// Select the selected subentity
		entLauncher.selectEntity(selEntity);

		// Show the subentity edition dialog
		entLauncher.entityDialog.open();
*/
	}

	/**
	 * Opens the edition dialog that enables the user to update or view the
	 * instance data of a multiple selection detail subentity.
	 * 
	 * @param entData
	 *            SubentityOT, data of the detail subentity to select.
	 * @param parentGuiName
	 *            String,
	 * @param selEntity
	 *            long, id of the selected instance of the subentity.
	 * @param readonly
	 *            boolean, true for enabling the read-only mode (only view);
	 *            false for allowing modification of the showed data.
	 */
	public void showSubentityDialog(SubentityOT entData, String parentGuiName,
			long selEntity, boolean readonly) {
/*		this.logger.info("ÇÇÇÇ SHOWING SUBENTITY DIALOG: "
				+ entData.getSubentityData().getKey() + ", " + this.entSelView
				+ " ÇÇÇÇ");
		// Get the entity launcher factory for creating a new entity launcher
		// that will handle the entity events.
		EntityLauncherFactory factory = ClientContext.getInstance()
				.getEntityLauncherFactory(entData.getSubentityData().getKey());

		// Get the entity launcher instance that will handle the entity events
		EntityLauncher entLauncher = factory.getEntityLauncher(parentGuiName);

		this.logger.info("GOT ENTITY LAUNCHER: " + entLauncher);

		if (entLauncher != null) {
			entLauncher.initEntityLauncher(this.logger, this.entityEditGuiName, null);
		} else
			this.logger.error(ERROR_ENTITY_NOHELPERINSTANCE);

		// Build the subentity edition dialog
		entLauncher.buildEditEntityGUI();

		// Select the selected subentity
		entLauncher.selectEntity(selEntity);

		// Show the subentity edition dialog
		entLauncher.entityDialog.open();
*/
	}

	/**
	 * Gets the entity dialog instance used for showing the entity data.
	 * 
	 * @return SwtDialog, instance of the entity's dialog.
	 */
	protected SwtDialog getEntityDialog() {
		// If it's the first time the entity dialog is accessed
		// (entityDialog == null) --> Build the dialog from the glade.
		if (this.entityDialog == null) {
			this.buildEntityDialog();
		}

		// Return the existing entity dialog instance.
		return this.entityDialog;
	}

	/**
	 * Sets up the entity dialog instance used for showing the entity data.
	 * 
	 * @param entityDialog
	 *            SwtDialog, instance of the entity's dialog.
	 */
	protected void setEntityDialog(SwtDialog entityDialog) {
		this.entityDialog = entityDialog;
	}

	/**
	 * Builds the entity dialog window from the corresponding glade interface
	 * file. Stores the entity dialog instance for posterior accesses.
	 */
	protected abstract void buildEntityDialog();

	/**
	 * Enable/Disable the edition controls of the entity view, for switching the
	 * entity view into read-only or edition mode.
	 * 
	 * @param enabled
	 *            boolean, True for switching into edition mode; False for
	 *            switching into read-only mode.
	 */
	protected abstract void setEditionMode(boolean enabled);

	/**
	 * Builds the edit entity dialog window from the corresponding glade
	 * interface file. Stores the entity dialog instance for posterior accesses.
	 */
	public void buildEditEntityGUI() {
		this.buildEntityDialog();
	}

	/**
	 * Inits the entity launcher context and prepares the launcher to be
	 * started.
	 * 
	 * @param logger Logger, logger instance for printing logging messages.
	 * @param parentGuiName String, name of the JavaGlade instance that
	 * built the parent where the entity will be embedded.
	 * @param parentPanel Composite, parent panel where the entity contents
	 * will be embedded.
	 */
	public void initEntityLauncher(Logger logger, Gui parentGui, SwtWidget parentPanel) {
		ClientContext.getInstance().getLogger().info(
				"Initializing entity: " + this.entityData.getName());
		this.logger = logger;
		this.parentGui = parentGui;
		this.parentPanel = parentPanel;

		// Check if the entity logger instance is OK
		this.entityReady = this.logger != null;

		if (this.logger != null) {
			this.logger.debug(String.format(
					"Entity launcher has been initialized - %b!",
					this.entityReady));
		} else {
			ClientContext.getInstance().getLogger().debug(
					String.format("Entity launcher has been initialized - %b!",
							this.entityReady));
		}

		// Check if the entity Data is OK
		if (this.entityData != null && this.entityData.getName() != null
				&& this.entityData.getName().length() > 0) {
			this.entityGuiName = InterfaceExplica.EXPLICA_ENTITY_GLADE_NAME
					+ "_" + this.entityData.getKey();
			this.entityEditGuiName = InterfaceExplica.EXPLICA_EDIT_GLADE_NAME
					+ "_" + this.entityData.getKey();
			this.entitySelectionGuiName = InterfaceExplica.EXPLICA_SUBENTITY_SELECTION_GLADE_NAME
					+ "_" + this.entityData.getKey();
		} else
			this.entityReady = false;

		// Check if the parent GUI exists
		if (this.parentGui == null)
			this.entityReady = false;

		if (this.entityReady)
			ClientContext.getInstance().getLogger().info("Entity: " + this.entityData.getName()
							+ " succesfully initialized!");
	}

	/**
	 * Builds the entity GUI and show it on screen to the user.
	 */
	public ExplicaEntityView buildEntity() {
		this.entityDetailView = null;
		if (!this.entityReady || this.entityData == null) {
			if (this.logger != null)
				logger.error(ERROR_START_ENTITY);
			else
				ClientContext.getInstance().getLogger().error(
						ERROR_START_ENTITY);
		} else {
			this.logger.debug(String.format(ENTITY_START, this.entityData
					.getName()));
			
			// Get an available entity view component
			this.entView = ClientContext.getInstance().getAvailableEntityView();

			// If any error has taken place during entity view construction
			if (this.entView == null) {
				if (this.logger != null)
					this.logger.error(ERROR_BUILD_ENTITY_PANEL);
				else
					ClientContext.getInstance().getLogger().error(
							ERROR_BUILD_ENTITY_PANEL);
			}

			// Get the parent panel where the entity view component will be embedded
			this.entView.showEntityView(this.parentGui, this, this.logger, this.parentPanel);
		}
		
		return this.entView;
	}

	/**
	 * Builds the entity GUI and show it on screen to the user. The entity GUI
	 * will be embedded into the parent composite widget.
	 * 
	 * @param parent
	 *            Composite, parent holder for embedding the entity view.
	 * @param subentityData
	 *            SubentityOT, data of the subentity to build if the entity
	 *            launcher will be used to handle a multi-selection detail
	 *            entity view.
	 * @param rootName
	 *            String, name of the root widget that will be embedded into the
	 *            master entity edition panel.
	 * @return ExplicaDetailEntityView, the entity detail view built.
	 */
	public ExplicaDetailEntityView buildEntity(SwtWidget parent,
			MultiSelectionSubentityOT subentityData, String rootName) {
		this.entView = null;

		if (!this.entityReady || this.entityData == null) {
			if (this.logger != null)
				logger.error(ERROR_START_ENTITY);
			else
				ClientContext.getInstance().getLogger().error(
						ERROR_START_ENTITY);
		} else {
			this.logger.debug(String.format(ENTITY_START, this.entityData
					.getName()));
			this.logger.debug("Building the detail entity panel: "
					+ this.entityData.getName() + " [" + parent.getWidgetName() + "]");
			this.entityDetailView = new ExplicaDetailEntityView(
					this.parentGui, parent, this.logger, subentityData, this, rootName);

			this.entityDetailView.buildEntityView();

			// Fill the entity table with the existing registries
			if (this.entityDetailView != null) {
				this.entityDetailView.fillEntityTable();
			}
			
			// Create the entity selection dialog
			this.connectSubentityButtons();

			// If any error has taken place during entity view construction
			if (this.entityPanel == null) {
				if (this.logger != null)
					this.logger.error(ERROR_BUILD_ENTITY_PANEL);
				else
					ClientContext.getInstance().getLogger().error(
							ERROR_BUILD_ENTITY_PANEL);
			}
		}

		return this.entityDetailView;
	}

	/**
	 * Connects the entity edition buttons to their correspondent event
	 * handlers.
	 */
	protected void connectEditEntityButtons() {
		this.logger.debug(String.format(
				"Connecting entity edition buttons [%s] --> %s, %s, %s ",
				this.entityEditGuiName, this, this.entEditView, this.entEditView.getGui()));
		// Get the entity edition Save button widget

		Button saveButton = (Button)this.entEditView.getGui().getWidget(
				InterfaceExplica.EXPLICA_ENTITYEDITION_SAVE_BUTTON_NAME);
		// Connect the button clicked signal to its handler
		ExplicaGUIBuilder
				.getInstance()
				.connectSignal(
						InterfaceGladeGtk.GTK_SIGNAL_TYPE_CLICKED,
						saveButton,
						InterfaceExplica.EXPLICA_ENTITY_EDITION_SAVE_BUTTON_CLICKED_HANDLER,
						this.entEditView);
		this.logger.debug(String.format(
				"Entity Edition (%s) Save button connected: %s!",
				this.entityData.getName(), saveButton));

		// Get the entity edition Cancel button widget
		Button cancelButton = (Button)this.entEditView.getGui().getWidget(
				InterfaceExplica.EXPLICA_ENTITYEDITION_CANCEL_BUTTON_NAME);
		// Connect the button clicked signal to its handler
		ExplicaGUIBuilder
				.getInstance()
				.connectSignal(
						InterfaceGladeGtk.GTK_SIGNAL_TYPE_CLICKED,
						cancelButton,
						InterfaceExplica.EXPLICA_ENTITY_EDITION_CANCEL_BUTTON_CLICKED_HANDLER,
						this.entEditView);
		this.logger.debug(String.format(
				"Entity Edition (%s) Cancel button connected: %s!",
				this.entityData.getName(), cancelButton));

		// Get the entity edition Undo button widget
		Button undoButton = (Button)this.entEditView.getGui().getWidget(
				InterfaceExplica.EXPLICA_ENTITYEDITION_UNDO_BUTTON_NAME);
		// Connect the button clicked signal to its handler
		ExplicaGUIBuilder
				.getInstance()
				.connectSignal(
						InterfaceGladeGtk.GTK_SIGNAL_TYPE_CLICKED,
						undoButton,
						InterfaceExplica.EXPLICA_ENTITY_EDITION_UNDO_BUTTON_CLICKED_HANDLER,
						this.entEditView);
		this.logger.debug(String.format(
				"Entity Edition (%s) Undo button (%s) connected: %s!",
				this.entityData.getName(),
				InterfaceExplica.EXPLICA_ENTITYEDITION_UNDO_BUTTON_NAME,
				undoButton));
	}

	/**
	 * Gets the entity data.
	 * 
	 * @return EntityOT, entity data.
	 */
	public EntityOT getEntity() {
		return entityData;
	}

	/**
	 * Sets up the entity name.
	 * 
	 * @param name
	 *            String, entity name.
	 */
	public void setEntity(EntityOT entity) {
		this.entityData = entity;
	}

	/**
	 * Gets the index of an instance (registry) of the entity, searching by the
	 * primary key (internal id).
	 * 
	 * @param id
	 *            Long, value of the entity instance to search for.
	 * @return int, index of the registry in the searched entities list if the
	 *         searched registry exists; -1 in any other case.
	 */
	protected int indexOf(Long id) {
		int index = -1;

		if (this.lRegistries != null && this.lRegistries.size() > 0) {
			boolean found = false;

			for (int i = 0; i < lRegistries.size() && !found; i++) {
				BaseVO reg = lRegistries.get(i);
				found = reg.equals(id);
				index = i;
			}
		}

		return index;
	}

	public void saveEntityRegistry() {
		OperationResult result = new OperationResult();
/*		if (this.isDetail()) {
			result = this.saveSubentity();
			
			this.logger.info(result.getFormattedResult());
		} // if detail
		else {
*/
			result = this.saveEntity();
	
			this.logger.info(result.getFormattedResult());
//		} // else no detail
		
		// If the result of the save operation was OK --> close the dialog
		if (result != null && result.getResult() == OperationResult.RESULT_OK) {
			// Update the entity registries table contents with the saved values
			System.out.println("REGISTROS TRAS SALVAR ("
					+ this.lRegistries.size() + "): " + this.lRegistries);
			this.logger.debug("EntityLauncher: " + this + " Updating view: " + this.entView + ", " + this.entityDetailView);
			this.logger.debug("Updating view: " + this.lRegistries.size() + " subentities");
			if (this.entView != null)
				this.entView.fillEntityTable(this.formatRegistries());
			else if (this.entityDetailView != null)
				this.entityDetailView.fillEntityTable(this.formatRegistries());

			// Close the entity edition dialog
			this.getEntityDialog().close();

			// Get the selected entity registry
			Long selectedId = this.getSelectedId();
			
			// Reselect the edited item in the entity tree
			if (selectedId != null) {
				Tree entityTree = this.getEntityTree();
				this.logger.debug("Entity tree found: " + entityTree);
				int index = this.indexOf(selectedId);
				entityTree.setSelection(entityTree.getItem(index));
			}
		}
		// else some errors have been produced --> show the errors to the user
		else {
			// Localize the result message errors into the user client locale
			OperationResult localizedResult = ClientContext.getInstance()
					.localizeOperationResult(result);

			// Show a message box with the result error messages.
			ExplicaGUIBuilder.getInstance().showConfirmationDialog(
					this.entityDialog.getShell(),
					localizedResult.getFormattedResult(),
					String.format("Error saving entity (%s) registry ...",
							this.entityData.getName()), SWT.ICON_ERROR, SWT.OK);
		}
	}

	public void cancelEntityEdition() {
		Tree entityTree = this.getEntityTree();
		this.logger.debug("Entity tree found: " + entityTree);

		// Reselect the selected entity registry
		Long selectedItem = null;
		TreeItem[] selItems = entityTree.getSelection();
		if (selItems != null && selItems.length > 0) {
			selectedItem = new Long(selItems[0].getText(0));
			this.selectEntity(selectedItem);
		} // for each selected item

		// Close the entity edition dialog
		this.getEntityDialog().close();
	}

	public void undoEntityEdition() {
		Long selectedId = this.getSelectedId();

		this.selectEntity(selectedId);
		this.fillEntityData();
	}
	
	/**
	 * Handler for the subentity selection buttons (magnifying glass buttons) clicked.
	 * Shows the selection dialog for selecting a valid instance of a subentity.
	 * @param e Event, magnifying glass button clicked event data.
	 */
	public void on_entitySelectionButton_clicked(Event e) {
		Button subentityButton = (Button)e.widget;
		
		// Get the entity data corresponding to the clicked entity selection button
		SubentityOT entData = (SubentityOT)subentityButton.getData();
		
		this.showSelectionDialog(entData);
	}

	/**
	 * Shows a confirmation dialog with a message to the user asking him to
	 * confirm the entity delete process.
	 * 
	 * @return boolean, True if the user confirms the delete process; False in
	 *         any other case.
	 */
	protected boolean confirmEntityDelete() {
		boolean isConfirmed = false;
		System.out.println("Confirmando el borrado de la entidad....");

		Shell parentShell = null;
		
		if (!this.isDetail() && this.entView != null)
			parentShell = this.entView.getGui().getParentWindow().getShell();
		else if (this.isDetail() && this.entityDetailView != null)
			parentShell = this.entityDetailView.getGui().getParentWindow().getShell();
		
		if (this.entityData != null && parentShell != null) {
			System.out
					.println("Mostrando el diálogo de confirmación de borrado de la entidad....");
			int buttonID = ExplicaGUIBuilder
					.getInstance()
					.showConfirmationDialog(
							parentShell,
							String.format(
											"The selected registry (%s - %d) will be removed from the system.\n"
													+ "Are you sure you want to delete this item?",
											this.entityData.getName(), this
													.getSelectedId()),
							String.format("Removing entity (%s) registry ...",
									this.entityData.getName()),
							SWT.ICON_QUESTION, SWT.YES | SWT.NO);

			System.out
					.println("Botón pulsado en la ventana de confirmación de borrado: "
							+ buttonID);

			isConfirmed = buttonID == SWT.YES;
		} else {
			System.out.println("ALGO ES NULL: " + this.entityData + ", " + this.entView + ", " + this.entityPanel + ", " + this.entityDetailView + ", " + parentShell);
			isConfirmed = false;
		}

		System.out.println("Confirmación de borrado de la entidad: "
				+ isConfirmed);

		return isConfirmed;
	}

	public ArrayList formatRegistries() {
		return this.formatRegistries(this.lRegistries);
	}

	public ArrayList formatRegistries(ArrayList lRegistries) {
		ArrayList<RegistryOT> result = new ArrayList<RegistryOT>();
		// For each registry format the data of the entity as String[] ready to
		// be printed out in the tree.
		for (int i = 0; lRegistries != null && i < lRegistries.size(); i++) {
			BaseVO prod = (BaseVO) lRegistries.get(i);
			String[] lValues = prod.format(this.entityData.getIdField(),
					this.entityData.getLFields());

			RegistryOT reg = new RegistryOT(prod.getInternalId(), "id", lValues);

			result.add(reg);
		}

		return result;
	}

	public Widget getWidget(String widgetName) {
//		return ExplicaGUIBuilder.getInstance().getWidget(
//				this.getEntityEditViewName(this.parentGuiName), widgetName);
		if (this.entEditView != null && this.entEditView.getGui() != null)
			return this.entEditView.getGui().getWidget(widgetName);
		else
			return null;
	}
	
	public SwtWidget getSwtWidget(String widgetName) {
//		return ExplicaGUIBuilder.getInstance().getWidget(
//				this.getEntityEditViewName(this.parentGuiName), widgetName);
		if (this.entEditView != null && this.entEditView.getGui() != null)
			return this.entEditView.getGui().getSwtWidget(widgetName);
		else
			return null;
	}
	
	protected Widget getEntityWidget(String widgetName) {
		if (this.entView != null)
			return this.entView.getGui().getWidget(widgetName);
		else if (this.entityDetailView != null)
			return this.entityDetailView.getGui().getWidget(widgetName);
		else
			return null;
	}

	public SwtDialog getDialog(String dialogName) {
		if (this.entEditView != null && this.entEditView.getGui() != null)
			return this.entEditView.getGui().getDialog(dialogName);
		else
			return null;
	}

	public void printWidgets() {
		if (this.entityReady)
			this.entEditView.getGui().printWidgets(this.logger);
		else
			ClientContext.getInstance().getLogger().error(
					"ENTITY NOT READY: " + this.entityData.getName());
	}

	public String getEntityEditViewName(String parentGuiName) {
		if (InterfaceExplica.EXPLICA_CORE_GLADE_NAME.equals(parentGuiName))
			return this.entityEditGuiName;
		else
			return parentGuiName + "\\" + this.entityEditGuiName;

//		return this.entityEditGuiName;
	}

	public String getEntityViewName(String parentGuiName) {
		return parentGuiName + "\\" + this.entityGuiName;
	}

	protected void fillEntityExtensionTable(String codExtTable) {
		// Fill the column headers of the catalog tree view
		Tree extCatalog = (Tree) this.getWidget(
				InterfaceExplica.EXPLICA_ENTITY_EXTENSION_CATALOG_NAME);
		extCatalog.setHeaderVisible(true);

		// Delete the previous contents on the catalog tree
		extCatalog.clearAll(true);
		extCatalog.removeAll();

		// Add the tree item editor
		EntityExtensionCatalogListener listener = new EntityExtensionCatalogListener(
				extCatalog);
		extCatalog.addListener(SWT.Selection, listener);

		// Add the headers to the entity extension catalog
		int columnWidth = (extCatalog.getParent().getParent().getParent()
				.getClientArea().width - 15) / 3;
		TreeColumn column = new TreeColumn(extCatalog, SWT.LEFT);
		column.setText(ClientContext.getInstance().getI18n().tr(
				InterfaceExplica.EXPLICA_ENTITY_EXTENSION_CATALOG_ID_COLUMN));
		column.setWidth(columnWidth);
		column.setMoveable(false);
		column.setResizable(false);
		column = new TreeColumn(extCatalog, SWT.LEFT);
		column
				.setText(ClientContext
						.getInstance()
						.getI18n()
						.tr(
								InterfaceExplica.EXPLICA_ENTITY_EXTENSION_CATALOG_VALUE_COLUMN));
		column.setWidth(columnWidth);
		column.setMoveable(false);
		column.setResizable(false);
		column = new TreeColumn(extCatalog, SWT.LEFT);
		column.setText(ClientContext.getInstance().getI18n().tr(
				InterfaceExplica.EXPLICA_ENTITY_EXTENSION_CATALOG_TYPE_COLUMN));
		column.setWidth(columnWidth);
		column.setMoveable(false);
		column.setResizable(false);

		// Get the extension field values for the edited entity
		try {
			CommonManager manager = this.getRemoteCommonManager();
			this.logger.debug("CommonManager located");
			ExtTableOT extTable = manager
					.getExtensionTableDefinition(codExtTable);

			Map m = manager.getExtendedItemValues(this.getSelectedId(),
					codExtTable);
			this.logger.debug(String.format(
					"Extension values located for entity [%s, %d] = %s",
					codExtTable, this.getSelectedId(), m));

			if (extTable != null && extTable.getFieldValues() != null) {
				Iterator it = extTable.getFieldValues().keySet().iterator();
				int i = 0;
				while (it != null && it.hasNext()) {
					String codExtField = (String) it.next();
					ExtFieldOT extField = (ExtFieldOT) extTable
							.getFieldValues().get(codExtField);
					this.logger.debug(String.format(
							"New extension item: %s = %s", codExtField,
							extField));
					ExtFieldOT extFieldVal = m != null ? (ExtFieldOT) m
							.get(codExtField) : null;
					String[] lValues = new String[] {
							extField.getFieldDescription(),
							extFieldVal != null ? extFieldVal
									.getValueAsString() : "",
							ClientContext.getInstance().getI18n().tr(
									extField.getFieldTypeAsString()) };

					this.logger.debug(lValues);

					// Add extension field to the entity extension catalog
					TreeItem treeItem = (TreeItem) ExplicaGUIBuilder
							.getInstance()
							.getToolkit()
							.treeItem(
									extCatalog,
									InterfaceExplica.EXPLICA_ENTITY_EXTENSION_TREEITEM_NAME
											+ "_" + codExtField, lValues, null,
									i);
					treeItem.setData(extField);

					// Add the widget to the catalog
					if (this.entView != null) {
						this.entView.getGui().addWidget(
								InterfaceExplica.EXPLICA_ENTITY_EXTENSION_TREEITEM_NAME	+ "_" + codExtField, 
								treeItem, 
								InterfaceExplica.EXPLICA_ENTITY_EXTENSION_CATALOG_NAME);
					}
					else if (this.entityDetailView != null) {
						this.entityDetailView.getGui().addWidget(
								InterfaceExplica.EXPLICA_ENTITY_EXTENSION_TREEITEM_NAME	+ "_" + codExtField, 
								treeItem, 
								InterfaceExplica.EXPLICA_ENTITY_EXTENSION_CATALOG_NAME);
					}

					i++;
				}
			}
		} catch (AccessException aEx) {
			this.logger
					.error(
							"Se rechazó el acceso. Su sistema no tiene los permisos necesarios para realizar la operación remota!",
							aEx);
			aEx.printStackTrace();
		} catch (RemoteException rEx) {
			this.logger
					.error(
							"No se encontró el servicio o hubo errores al llamar a los métodos remotos!",
							rEx);
			rEx.printStackTrace();
		} catch (ExtTableException ex) {
			ex.printStackTrace();
			this.logger
					.error(
							"No se ha podido cargar el catalogo de propiedades de extension para la tabla: "
									+ codExtTable, ex);
			this.logger.error(ex.getLocalizedMessage());
		} catch (ExplicaException eEx) {
			this.logger
					.error(
							"No se ha podido cargar el catalogo de propiedades de extension para la tabla: "
									+ codExtTable, eEx);
			eEx.printStackTrace();
		}
	}

	protected OperationResult saveEntityExtensionTable(String codExtTable) {
		OperationResult result = new OperationResult();
		// Fill the column headers of the catalog tree view
		Tree extCatalog = (Tree) this.entEditView.getGui().getWidget(
				InterfaceExplica.EXPLICA_ENTITY_EXTENSION_CATALOG_NAME);

		// Get the extension field values for the edited entity
		try {
			CommonManager manager = this.getRemoteCommonManager();
			this.logger.debug("CommonManager located");
			ArrayList<ExtFieldOT> lExtFields = new ArrayList<ExtFieldOT>();

			for (int i = 0; extCatalog != null && i < extCatalog.getItemCount(); i++) {
				TreeItem item = extCatalog.getItem(i);
				ExtFieldOT extField = (ExtFieldOT) item.getData();
				extField.updateValue(item.getText(1));
				lExtFields.add(extField);
			}

			result = manager.saveExtendedItemValues(lExtFields, this
					.getSelectedId());
		} catch (AccessException aEx) {
			this.logger
					.error(
							"Se rechazó el acceso. Su sistema no tiene los permisos necesarios para realizar la operación remota!",
							aEx);
			aEx.printStackTrace();
		} catch (RemoteException rEx) {
			this.logger
					.error(
							"No se encontró el servicio o hubo errores al llamar a los métodos remotos!",
							rEx);
			rEx.printStackTrace();
		} catch (ExtTableException ex) {
			ex.printStackTrace();
			this.logger
					.error(
							"No se ha podido guardar el catalogo de propiedades de extension para la tabla: "
									+ codExtTable, ex);
			this.logger.error(ex.getLocalizedMessage());
		} catch (ExplicaException eEx) {
			this.logger
					.error(
							"No se ha podido guardar el catalogo de propiedades de extension para la tabla: "
									+ codExtTable, eEx);
			eEx.printStackTrace();
			result.addResultMessage(OperationResult.RESULT_ERROR, eEx
					.getResMsg());
		}

		return result;

		/*
		 * if (result.getResult() != OperationResult.RESULT_OK) {
		 * ExplicaGUIBuilder.getInstance().showConfirmationDialog(
		 * this.entityPanel.getShell(), "Error", String.format("There have been
		 * errors during the update operation:\n%s",
		 * result.getFormattedResult()), SWT.ICON_ERROR, SWT.OK); }
		 */
	}

	private CommonManager getRemoteCommonManager() throws ExplicaException {
		try {
			// El servidor de registro de RMI devuelve un objeto remoto genérico
			// que debe ser convertido al tipo correspondiente. Ojo: El nombre
			// por el
			// que buscamos debe coincidir con el que se le dio al servicio en
			// el
			// momento en que se registró (WarehouseManagerImpl.java)
			Registry registry = LocateRegistry
					.getRegistry(InterfaceExplica.RMI_REGISTRY_PORT);
			System.out.println("Registry located");
			CommonManager manager = (CommonManager) registry
					.lookup(InterfaceExplica.JNDI_COMMON_MANAGER_EXPORT_NAME);
			System.out.println("CommonManager located");

			return manager;
		} catch (AccessException aEx) {
			System.err
					.println("Se rechazó el acceso. Su sistema no tiene los permisos necesarios para realizar la operación remota!");
			aEx.printStackTrace();

			throw new ExplicaException(
					ClientContext
							.getInstance()
							.getMsgCatalog()
							.newResultMessage(
									InterfaceErrors.ERR_RMI_NO_ACCESS,
									aEx,
									(Object) InterfaceExplica.JNDI_WAREHOUSE_MANAGER_EXPORT_NAME,
									(Object) null));
		} catch (NotBoundException nEx) {
			System.err
					.println("El nombre del objeto no está asociado a un objeto remoto registrado!");
			nEx.printStackTrace();

			throw new ExplicaException(
					ClientContext
							.getInstance()
							.getMsgCatalog()
							.newResultMessage(
									InterfaceErrors.ERR_RMI_NOT_BOUND,
									nEx,
									(Object) InterfaceExplica.JNDI_WAREHOUSE_MANAGER_EXPORT_NAME,
									(Object) null));
		} catch (RemoteException rEx) {
			System.err
					.println("No se encontró el servicio o hubo errores al llamar a los métodos remotos!");
			rEx.printStackTrace();

			throw new ExplicaException(
					ClientContext
							.getInstance()
							.getMsgCatalog()
							.newResultMessage(
									InterfaceErrors.ERR_RMI_METHOD_NOT_FOUND,
									rEx,
									(Object) InterfaceExplica.JNDI_WAREHOUSE_MANAGER_EXPORT_NAME,
									(Object) null));
		}
	}

	/**
	 * Sets the list of registries that are showed in the entity view controlled
	 * by the Entity Launcher instance. It's used for detail entities where
	 * queries are made in the master entity launcher.
	 * 
	 * @param lRegistries
	 *            ArrayList<BaseVO>, list of shown registries of the entity.
	 */
	public void setRegistries(ArrayList<BaseVO> lRegistries) {
		this.lRegistries = lRegistries;
	}

	/**
	 * Gets the entity launcher factory of a subentity.
	 * 
	 * @param entOT
	 *            EntityOT, data of the subentity.
	 * @return EntityLauncherFactory, instance of the factory of EntityLaunchers
	 *         for this entity's GUI.
	 */
	protected EntityLauncherFactory getEntityLauncherFactory(EntityOT entOT) {
		EntityLauncherFactory factory = null;
		if (entOT != null && entOT.getKey() != null
				&& entOT.getKey().length() > 0) {
			factory = ClientContext.getInstance().getEntityLauncherFactory(
					entOT.getKey());
			if (factory == null) {
				ClientContext.getInstance().initEntityLauncherFactory(entOT,
						this.logger);
				factory = ClientContext.getInstance().getEntityLauncherFactory(
						entOT.getKey());
			}
		}

		return factory;
	}
	
	protected Tree getEntityTree() {
		if (this.entView != null)
			return this.entView.getEntityTreeWidget();
		else if (this.entityDetailView != null)
			return this.entityDetailView.getEntityTreeWidget();
		else
			return null;
	}
	
	public BaseVO getRegistry(long id) {
		int index = this.indexOf(id);
		if (this.lRegistries != null && index >= 0 && index < lRegistries.size()) {
			return lRegistries.get(index);
		}
		else
			return null;
	}
	
	/**
	 * Opens the selection dialog that enables the user to select an instance
	 * of a subentity.
	 * @param entData SubentityOT, data of the detail subentity to select.
	 */
	public void showSelectionDialog(SubentityOT entData) {
		this.logger.info("ÇÇÇÇ SHOWING SELECTION DIALOG [" + this.entityData.getKey() + "]: "
				+ entData.getSubentityData().getKey() + ", " + this.entSelView
				+ " ÇÇÇÇ");
/*		ExplicaEntitySelectionView entSelView = ClientContext.getInstance().getAvailableEntitySelectionView();
		
		entSelView.showSubentitySelection(entData, this.getEntityDialog().getShell());
*/
		if (this.entSelView != null) {
			this.entSelView.showSubentitySelection(entData);
		}
	}
	
	/**
	 *Indicates whether is a main entity or is embedded in another
	 */
	public boolean isDetail() {
		if (this.entityDetailView != null)
			return true;
		else if (this.entView != null)
			return false;
		else {
			fireExceptionAndExit("Internal error in CommonClient class. All Views are null");
			return false;
		}

	}
	
	/**
	 * Fire a exception and stop the program
	 * 
	 * @param msg
	 */
	public void fireExceptionAndExit(String msg) {
		ResultMessage result = new ResultMessage(OperationResult.RESULT_ERROR,
				new Exception(msg));
		try {
			throw new ExplicaException(result);
		} catch (ExplicaException e) {
			System.out.println(msg);
			e.printStackTrace();
			System.exit(-1);
		}
	}
	
	private OperationResult saveSubentity() {
		OperationResult result = new OperationResult();
		
		if (this.entityDetailView == null)
			fireExceptionAndExit("Internal error in CommonClient class. All Views are null");
		
		SubentityOT subEnt = this.entityDetailView.getSubentityData();
		subEnt.getParentEntity().selectSubentity(subEnt.getParentFieldId(), this.getSelectedEntity());
		
		result.addResultMessage(OperationResult.RESULT_OK, ClientContext.getInstance().getMsgCatalog().newResultMessage(1));
		return result;
	}
	
	/**
	 * Returns tag Id assigned to CVS source file.
	 */
	public static String getRevision() {
		return "$Id: EntityLauncher.java,v 1.23 2009-10-07 10:19:39 juancarlos Exp $";
	}
}
